import java.awt.Color;
import java.awt.Point;
import java.io.*;
import java.net.*;
import java.util.*;

public class MDServer 
{
	private List<Socket> clientList = new ArrayList<Socket>();
    private int num = 1;
    public LinkedList<ShapeObject> ShapeObjects = new LinkedList<ShapeObject>();
    public LinkedList<LinkedList> FileList = new LinkedList<LinkedList>();
    
    public static void main (String [] args) 
    {
    	
    	int port = 8888;
    	if (args.length > 0) port = Integer.parseInt(args[0]);
    	
    	MDServer cs = new MDServer();
//    	code to populate the file list in MDServer
    	for(int i = 0; i < 5; i++){
    		LinkedList<ShapeObject> tempList = new LinkedList<ShapeObject>();
    		int sx = i*10; int sy = i*10;
    		int ex = i*10 + 50; int ey = i*10 + 50;
    		
    		tempList.add(new RectangleObject(new Point(sx,sy), new Point(ex,ey), Color.blue));
    		tempList.add(new OvalObject(new Point(sx + 50,sy), new Point(ex + 50,ey), Color.green));
    		tempList.add(new LineObject(new Point(sx,sy + 50), new Point(ex,ey + 50), Color.green));
    		cs.FileList.add(tempList);
    	}
//    	code to copy a file in FileList and set ShapeObjects contents to that copy
    	if(! cs.setShapeObjectsToFile(2)){
    		cs.ShapeObjects.add(new RectangleObject(new Point(5,5), new Point(50,50), Color.blue));
    	}
    	

    	cs.listen(port);
    }
    boolean setShapeObjectsToFile(int index){
    	if(FileList.size() - 1 < index){
    		return false;
    	}
    	ShapeObjects.clear();
    	try{
	    	for(int i = 0; i < FileList.get(index).size(); i++){
	    		ShapeObjects.add((ShapeObject)(FileList.get(index).get(i)));
	    	}
    	}catch(Exception e){
    		System.out.println("Exception thrown:");
    		e.printStackTrace();
    		return false;
    	}
    	return true;
    }
	void broadcastShapeObjects(){
		
		for (Socket s :  clientList) 
    	{
			ObjectOutputStream oos;
			try {
				oos = new ObjectOutputStream(s.getOutputStream());
				oos.writeObject(ShapeObjects);
			} catch (IOException e) {
				e.printStackTrace();
			}
    	}
	}
    void listen(int port) 
    {
    	try
    	{	
    	    ServerSocket listener = new ServerSocket(port);
        
    	    System.out.println(">>>> The MD Server <<<<");
    	    System.out.println("Telnet to " 
                               + InetAddress.getLocalHost().getHostName() 
    	    		       + " on port " + port);
    	    System.out.println("Use control-c to terminate MD Server.");
    
    	    while (true) 
    	    {
    	    	Socket client = listener.accept();
    	    	new MDHandler(client,this).start();
    	    	System.out.println("New client number " + num + " from " 
    	            		 + client.getInetAddress().getHostName()
    				 + " on client's port " + client.getPort());
    		add(client);
    	    }
    	}
    	catch (IOException e)
    	{   System.out.println(e);   }
    }
    
    synchronized void add(Socket s) 
    {
    	clientList.add(s);  num++;
    }  
    
    synchronized void remove(Socket s) 
    {
    	clientList.remove(s);  num--;
    }  
	
    synchronized void broadcast(String message, String source) throws IOException 
    {
    	// Sends the message to every client including source.

    	for (Socket s :  clientList) 
    	{
    	    PrintWriter p = new PrintWriter(s.getOutputStream(), true);
    	    p.println(source + ": " + message + "\n");	
    	}
    	System.out.println(source+ ": " + message + "\n");
    }
    synchronized void refreshShapeObjects(LinkedList<ShapeObject> sobjs){
    	ShapeObjects.clear();
  	  	for(int i=0; i<sobjs.size(); i++){
  	  		ShapeObjects.add(sobjs.get(i));
  	    }
    }
}
